package com.atguigu.common.component.tree;

import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: tianchao
 * @Date: 2020/8/20 16:53
 * @Description:
 */
@Component(value="simpleTreeHelper")
public class SimpleTreeHelper implements ITreeHelper {

    /**
     * 已root构建一棵树
     * @param sourceList
     * @param root
     * @param <T>
     */
    public <T extends ITree> void searchChildrenByRoot(List<T> sourceList,T root){
        Assert.notNull(root,"root根不能取null");
        //树形结构
        List<T> rootTreeList = this.buildTree(sourceList);
        //优化算法 减少循环次数
        Map<String, List<T>> mapList = sourceList.stream().filter( e -> e.getParentId() != null).collect(Collectors.groupingBy(e -> e.getParentId()));
        this.buildChildren(mapList, root);
    }

    /**
     * 构建树形结构
     * @param sourceList
     * @param <T>
     * @return
     */
    public <T extends ITree> List<T> buildTree(List<T> sourceList){
        if (CollectionUtils.isEmpty(sourceList)){
            return null;
        }
        //优化算法 减少循环次数
        // java8 分组 null 不能作为Map 的Key 过滤掉parentId为null 数据
        // 本身下面的循环就是上来就获取根，所以不会去找以null为父节点的数据
        Map<String, List<T>> mapList = sourceList.stream().filter( e -> e.getParentId() != null).collect(Collectors.groupingBy(e -> e.getParentId()));
        List<T> result = new ArrayList<>();
        for (T node : sourceList) {
            if (node.getParentId() == null || "".equals(node.getParentId())){
                buildChildren(mapList, node);
                result.add(node);
            }
        }
        return result;
    }

    /**
     * 构建树的辅助方法
     * @param mapList key是parentId , value是 记录是parentId的集合
     * @param node
     * @param <T>
     */
    private <T extends ITree> void buildChildren(Map<String, List<T>> mapList, T node) {
        List<T> children = mapList.get(node.getId());
        if (children == null) {
            return;
        }
        children.forEach(e->{
            buildChildren(mapList,e);
        });
        node.setChildren(children);

    }
}
